package org.circedroid.core;

import android.util.Log;
import android.widget.Toast;
import android.content.Context;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.IOException;
import java.util.Vector;

import org.circedroid.activity.R;

public abstract class GRiD{
	private String nomfichier;
	private Context context;

	private int _lgInfo;
	private int _idfile;
	
	private Double lonmin;
	private Double lonmax;
	private Double latmin;
	private Double latmax;
	private Double paslon;
	private Double paslat;
	private int dim;
	private Integer ordrerangement;
	private boolean codeprec;
	
	public GRiD(String nomfichier, Context context){
		this.nomfichier=nomfichier;
		this.context=context;
		this.loadFile();
	};
	
	public String getNomFichier(){return this.nomfichier;}
	
	public void loadFile(){
		this._lgInfo=0;
		
		try{
			String debutfichier=this.nomfichier.substring(0, this.nomfichier.indexOf("."));

			this._idfile = this.context.getResources().getIdentifier(debutfichier,"raw",this.context.getPackageName());

			InputStream ips = context.getResources().openRawResource(this._idfile);
			InputStreamReader ipsr=new InputStreamReader(ips);
			BufferedReader br=new BufferedReader(ipsr);
			String ligne;

			ligne=br.readLine();
			
			String[] mots=ligne.split("[ \t]+");
			this.lonmin=Double.parseDouble(mots[0]);
			this.lonmax=Double.parseDouble(mots[1]);
			this.latmin=Double.parseDouble(mots[2]);
			this.latmax=Double.parseDouble(mots[3]);
			this.paslon=Double.parseDouble(mots[4]);
			this.paslat=Double.parseDouble(mots[5]);
			this.ordrerangement=Integer.parseInt(mots[6]);
			this.dim = Integer.parseInt(mots[8]);
			this.codeprec = mots[9].equals("1");
			
			
			//On détermine la taille du premier bloc d'info
			char[] buf = new char[50];
			br.read(buf, 0, 50);
			String tmpligne = new String(buf);
  
			int nbBlank=this.dim; //Nombre d'espace à chercher
			this._lgInfo=0;
			Log.d("moi","je commence");
			int i=-1;
			while (nbBlank!=0){
				i=tmpligne.indexOf(" ",i+1);
				Log.d("moi","j'ai trouvé un blanc");
				nbBlank--;
				if (nbBlank==0){
					this._lgInfo=i;
					break;
				}
			}
			Log.d("moi", Integer.toString(_lgInfo));
			br.close();
		}
		catch (Exception e) {
			Toast.makeText(context, new String("Problème lors du chargement de ").concat(this.nomfichier), Toast.LENGTH_LONG).show();
			Toast.makeText(context, e.toString(), Toast.LENGTH_LONG).show();

		}
	}
	
	public Vector<String> strvalue(int ind, int size){
		Vector<String> result= new Vector<String>();
		
		InputStream ips = context.getResources().openRawResource(this._idfile);
		InputStreamReader ipsr=new InputStreamReader(ips);
		BufferedReader br=new BufferedReader(ipsr);
		char[] buf = new char[_lgInfo];
		char[] OneChar = new char[1];
		String strbuf;
		try {
			//On passe la ligne d'entete
			br.readLine();
			
			
			//premiere valeur
			//br.skipblock(ind, _lgInfo,this.codeprec);
			br.skipblock(ind, this.dim,this.codeprec);
		
			Log.d("moi","Skip "+ind+" et "+_lgInfo);
			
			//br.read(buf);
			//strbuf = new String(buf);
			strbuf = br.readblock(this.dim, this.codeprec);
			Log.d("moi",strbuf);
			result.add(new String(strbuf));
			/*if (this.codeprec){
				br.skip(2);
				br.read(OneChar);
				if (OneChar[0]==' '){
				} else {
					br.skip(1);
				}
			} else {
				br.skip(1);
			}
			*/
			
			
			//2e
			/*
			br.read(buf);
			strbuf = new String(buf);
			Log.d("moi",strbuf);
			result.add(new String(strbuf));
			if (this.codeprec){
				br.skip(2);
				br.read(OneChar);
				if (OneChar[0]==' '){
				} else {
					br.skip(1);
				}
			} else {
				br.skip(1);
			}
			*/
			strbuf = br.readblock(this.dim, this.codeprec);
			Log.d("moi",strbuf);
			result.add(new String(strbuf));
			
			//3e
			//br.skipblock(size-2,_lgInfo,this.codeprec);
			br.skipblock(size-2,this.dim,this.codeprec);

			/*br.read(buf);
			strbuf = new String(buf);
			Log.d("moi",strbuf);
			result.add(new String(strbuf));
			if (this.codeprec){
				br.skip(2);
				br.read(OneChar);
				if (OneChar[0]==' '){
				} else {
					br.skip(1);
				}
			} else {
				br.skip(1);
			}*/
			strbuf = br.readblock(this.dim, this.codeprec);
			Log.d("moi",strbuf);
			result.add(new String(strbuf));
			
			//4e
			/*br.read(buf);
			strbuf = new String(buf);
			Log.d("moi",strbuf);
			result.add(new String(strbuf));
			*/
			strbuf = br.readblock(this.dim, this.codeprec);
			Log.d("moi",strbuf);
			result.add(new String(strbuf));
			br.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}
	
	public Vector<Double> getValueGRiD(Double lonn, Double latt){
		Vector<Double> interp= new Vector<Double>();
				
		double lon = lonn*180.0/Math.PI;
		double lat = latt*180.0/Math.PI;
		if (lon>lonmax || lon<lonmin ||lat>latmax || lat<latmin){
			if (this.dim==1){
				Toast.makeText(this.context, this.context.getString(R.string.outgridalti), Toast.LENGTH_SHORT).show();
			} else {
				Toast.makeText(this.context, this.context.getString(R.string.outgrid3d), Toast.LENGTH_SHORT).show();
			}
			return null;
		}
		int ind;
		int indlat;
		int indlon;
		int sizelon;
		int sizelat;
		Double dlon;
		Double dlat;
		double valind;
		double valind1;
		double valindsl;
		double valindsl1;
		double val1;
		double val2;
		
		switch (this.ordrerangement) {
		case 2:
			ind=0;
			sizelon=(int) Math.round((this.lonmax-this.lonmin)/this.paslon)+1;
			Log.d("moi","sizelon"+sizelon);
			indlon=(int) Math.floor((lon-this.lonmin)/this.paslon)+1;
			indlat=(int) Math.floor((this.latmax-lat)/this.paslat)+1;
			Log.d("moi","indlon="+indlon);
			Log.d("moi","indlat="+indlat);
			ind=(indlat-1)*sizelon+indlon-1;
			dlon=lon-this.paslon*(indlon-1)-this.lonmin;
			dlat=this.latmax-this.paslat*(indlat-1)-lat;
			try {
				Vector<String> strval = this.strvalue(ind, sizelon);
				Vector<Vector<Double>> vectval = new Vector<Vector<Double>>();
				for (int i=0;i<4;i++){
					vectval.add(parsestrvalue(strval.get(i)));
				}
				for (int i=0;i<this.dim;i++){
					valind=0;
					valind1=0;
					valindsl=0;
					valindsl1=0;
					valind = vectval.get(0).get(i);
					valind1 = vectval.get(1).get(i);
					valindsl = vectval.get(2).get(i);
					valindsl1 = vectval.get(3).get(i);
					val1=(valind1-valind)/this.paslon*dlon+valind;
					val2=(valindsl1-valindsl)/this.paslon*dlon+valindsl;
					interp.add((val2-val1)/this.paslat*dlat+val1);
				}

			}
			catch (Exception e) {
				return null;
			}
			break;
			
		case 1:
			ind=0;
			sizelat=(int) Math.round((this.latmax-this.latmin)/this.paslat)+1;
			Log.d("moi","sizelat"+sizelat);
			indlon=(int) Math.floor((lon-this.lonmin)/this.paslon)+1;
			indlat=(int) Math.floor((this.latmax-lat)/this.paslat)+1;
			Log.d("moi","indlon="+indlon);
			Log.d("moi","indlat="+indlat);
			ind=(indlon-1)*sizelat+sizelat-indlat-1;
			dlon=lon-this.paslon*(indlon-1)-this.lonmin;
			dlat=this.latmax-this.paslat*(indlat-1)-lat;
			
			try {
				Vector<String> strval = this.strvalue(ind, sizelat);
				Vector<Vector<Double>> vectval = new Vector<Vector<Double>>();
				for (int i=0;i<4;i++){
					vectval.add(parsestrvalue(strval.get(i)));
				}
				for (int i=0;i<this.dim;i++){
					valind=0;
					valind1=0;
					valindsl=0;
					valindsl1=0;
					valind = vectval.get(1).get(i);
					valind1 = vectval.get(3).get(i);
					valindsl = vectval.get(0).get(i);
					valindsl1 = vectval.get(2).get(i);
					val1=(valind1-valind)/this.paslon*dlon+valind;
					val2=(valindsl1-valindsl)/this.paslon*dlon+valindsl;
					interp.add((val2-val1)/this.paslat*dlat+val1);
				}
				Log.d("moi",interp.toString());
			}
			catch (Exception e) {
				return null;
			}
			break;

		}
		return interp;
	}

	private Vector<Double> parsestrvalue(String str){
		String[] mots=str.split("[ \t]+");
		Vector<Double> result = new Vector<Double>();
		
		if (mots.length != this.dim){
			Log.d("moi","problème de dimension");
			return null;
		}
		Log.d("moi","parse des blocs de la grille :");
		Log.d("moi",str);
		for (int i=0;i<this.dim;i++)
			result.add(Double.parseDouble(mots[i]));
		
		return result;
	}
}